package com.tensquare.article.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.tensquare.article.client.NoticeClient;
import com.tensquare.article.dao.ArticleDao;
import com.tensquare.article.pojo.Article;
import com.tensquare.article.pojo.Notice;
import com.tensquare.util.IdWorker;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class ArticleService {

  @Autowired private ArticleDao articleDao;

  @Autowired private IdWorker idWorker;

  @Autowired private RedisTemplate<String, String> redisTemplate;

  @Autowired private NoticeClient noticeClient;

  @Autowired private RabbitTemplate rabbitTemplate;

  public List<Article> findAll() {
    return articleDao.selectList(null);
  }

  public Article findById(String id) {
    return articleDao.selectById(id);
  }

  /**
   * 添加文章
   *
   * @param article
   */
  public void add(Article article) {
    // 使用分布式id生成器生成id
    String id = idWorker.nextId() + "";
    article.setId(id);
    article.setVisits(0);
    article.setThumbup(0);
    article.setComment(0);

    articleDao.insert(article);

    // TODO 使用jwt获取当前用户的userid，也就是文章作者的id
    String authorId = "3";

    // 获取需要通知的读者
    String authorKey = "article_author_" + authorId;
    Set<String> set = redisTemplate.boundSetOps(authorKey).members();

    Notice notice;
    for (String uid : set) {
      // 消息通知
      notice = new Notice();
      notice.setReceiverId(uid);
      notice.setOperatorId(authorId);
      notice.setAction("publish");
      notice.setTargetType("article");
      notice.setTargetId(id);
      notice.setCreatetime(new Date());
      notice.setType("sys");
      notice.setState("0");

      noticeClient.add(notice);
    }
    // 入库成功，发送mq消息，内容是消息通知id
    rabbitTemplate.convertAndSend("article_subscribe", authorId, id);
  }

  public void update(Article article) {
    // articleDao.updateById(article);
    EntityWrapper<Article> wrapper = new EntityWrapper<>();
    wrapper.eq("id", article.getId());
    articleDao.update(article, wrapper);
  }

  public void delete(String id) {
    articleDao.deleteById(id);
  }

  public Page search(Map map, int page, int size) {
    EntityWrapper<Article> wrapper = new EntityWrapper<>();
    Set<String> fieldSet = map.keySet();
    for (String field : fieldSet) {
      // 条件查询：如果map.get("field")不为空，再判断field字段值与map.get("field")是否相同
      wrapper.eq(null != map.get(field), field, map.get(field));
    }
    Page page1 = new Page(page, size);
    List<Article> list = articleDao.selectPage(page1, wrapper);
    page1.setRecords(list);
    return page1;
  }

  public Boolean subscribe(String userId, String articleId) {
    String authorId = articleDao.selectById(articleId).getUserid();

    // 创建Rabbit管理器
    RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate.getConnectionFactory());
    // 声明exchange
    DirectExchange exchange = new DirectExchange("article_subscribe");
    rabbitAdmin.declareExchange(exchange);
    // 创建队列
    Queue queue = new Queue("article_subscribe_" + userId, true);
    // 声明exchange和queue的绑定关系
    Binding binding = BindingBuilder.bind(queue).to(exchange).with(authorId);

    String userKey = "article_subscribe_" + userId;
    String authorKey = "article_author_" + authorId;

    Boolean flag = redisTemplate.boundSetOps(userKey).isMember(authorId);
    if (flag) {
      // 取消订阅
      redisTemplate.boundSetOps(userKey).remove(authorId);
      redisTemplate.boundSetOps(authorKey).remove(userId);
      // 删除绑定的队列
      rabbitAdmin.removeBinding(binding);
      return false;
    } else {
      // 订阅
      redisTemplate.boundSetOps(userKey).add(authorId);
      redisTemplate.boundSetOps(authorKey).add(userId);
      // 添加队列和绑定队列
      rabbitAdmin.declareQueue(queue);
      rabbitAdmin.declareBinding(binding);
      return true;
    }
    // rabbitTemplate.convertAndSend("article_subscribe", );
  }

  public void thumbup(String userId, String articleId) {
    // 文章点赞
    Article article = articleDao.selectById(articleId);
    article.setThumbup(article.getThumbup() + 1);
    articleDao.updateById(article);

    // 消息通知(点赞成功后，给作者发送消息，点点通知)
    Notice notice = new Notice();
    notice.setReceiverId(article.getUserid());
    notice.setOperatorId(userId);
    notice.setAction("thumbup");
    notice.setTargetType("article");
    notice.setTargetId(articleId);
    notice.setCreatetime(new Date());
    notice.setType("user");
    notice.setState("0");
    noticeClient.add(notice);

    // 创建Rabbit管理器
    RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate.getConnectionFactory());
    // 创建队列，每个用户都有自己的队列，通过用户id进行区分
    Queue queue = new Queue("article_thumbup_" + article.getUserid(), true);
    rabbitAdmin.declareQueue(queue);
    //发送消息
    rabbitTemplate.convertAndSend("article_thumbup_" + article.getUserid(), articleId);
  }
}
